// tree-sitter的语法定义文件grammar.js
module.exports = grammar({
  name: 'dolphindb',

  rules: {
    // 语法的入口
    source_file: $ => repeat($._statement),
    // 语句由几个部分构成，并由可选的分号分隔:
    //  * 模块定义
    //  * 模块引用
    //  * 注释块
    //  * 函数块
    _statement: $ => seq(
      choice(
        $.module_declaration,
        $.use_statement,
        $.comment,
        $.function_declaration,
      ),
      optional(';')
    ),

    // 函数定义
    // def func(a, b) {}
    //   def关键字(可选)
    //   函数名
    //   参数列表
    //   函数体
    function_declaration: $ => seq(
      'def',
      $.identifier,
      $.parameter_list,
      $.function_block
    ),

    // 参数列表,在()内
    parameter_list: $ => seq(
      '(',
      optional($.parameters),
      ')'
    ),
    // 参数由','分割
    parameters: $ => seq(
      $.parameter,
      repeat(seq(',', $.parameter))
    ),
    // 参数由名称+[=表达式]组成
    parameter: $ => seq(
      $.identifier,
      optional(seq(
        '=',
        $.param_value_expr
      ))
    ),

    function_block: $ => $.ignored_block,

    ignored_block: $ => seq(
      '{',
      repeat(choice(
        $.comment,
        //$.string,
        $.nested_block,
        /[^{}]+/
      )),
      '}'
    ),
    nested_block: $ => seq(
      '{',
      repeat(choice(
        $.comment,
       // $.string,
        $.nested_block,
        /[^{}]+/
      )),
      '}'
    ),

    // 函数体
    // 主要由语句体构成,每条语句后可能有分号
    // 允许没有语句体
    block: $ => seq(
      '{',
      optional($.statement_block),
      '}'
    ),
    // 语句体不可以为空,至少有一个语句或者;
    statement_block: $ => repeat1(choice(
      $.expression_statement,
      $.comment
    )),

    expression_statement: $ => seq(
      optional($.expression),
      ';'
    ),

    // expression需要支持
    // 一个表达式可以是一个字符串、数字、变量、二元表达式
    // 二元表达式由两个表达式和一个操作符组成
    expression: $ => choice(
      $.string,
      $.number,
      $.datetime,
      $.identifier,
      $.array,
      $.string_vector,
      $.binary_expression
    ),

    // 参数默认值表达式
    param_value_expr: $ => choice(
      $.string,
      $.number,
      $.datetime,
      $.array,
      $.string_vector
    ),

    binary_expression: $ => prec.left(seq(
      $.expression,
      choice('=', '+', '-', '*', '/'),
      $.expression
    )),

    function_call: $ => seq(
      $.identifier,
      $.argument_list
    ),

    argument_list: $ => seq(
      '(',
      optional($.arguments),
      ')'
    ),

    arguments: $ => seq(
      $.expression,
      repeat(seq(',', $.expression))
    ),

    // 定义for(x in y){} 语句
    for_statement: $ => seq(
      'for',
      '(',
      $.identifier,
      'in',
      $.identifier,
      ')',
      $.for_block
      //'{',
      //repeat($.ignored_body_content),
      //'}'
    ),

    for_block: $ => $.block,

    // 变量名称
    identifier: $ => /[a-zA-Z_][a-zA-Z0-9_]*/,

    string: $ => choice(
      seq("'", /[^']*/, "'"),
      seq('"', /[^"]*/, '"')
    ),

    number: $ => /\d+/,
    datetime: $ => /[0-9]{4}\.[0-9]{2}\.[0-9]{2}([ ]*[0-9]{2}:[0-9]{2}:[0-9]{2}(\.[0-9]{3,})*)*/,
    primitives: $ => choice(
      $.string,
      $.number,
      $.datetime
    ),
    // 匹配`ETF`CS`AAA,除了`,`和空格外的字符
    string_vector: $ => /(`[^`, ]+)+/,
    //
    array: $ => seq(
      '[',
      repeat(seq($.primitives, ',')),
      ']'
    ),
    // 模块声明
    module_declaration: $ => seq(
      'module',
      $.module_name
    ),

    module_name: $ => choice(
      seq($.identifier, '::', $.identifier),
      $.identifier
    ),

    // 使用声明
    use_statement: $ => seq(
      'use',
      $.module_name
    ),

    // 注释
    comment: $ => choice(
      /\/\*[^*]*\*+(?:[^/*][^*]*\*+)*\//,  // 多行注释
      /\/\/[^\n]*/      // 单行注释
    )
  }
});

